﻿namespace BM.Tools.WebControls.MForm.Navigation.Predicates
{
    using System;

    using BM.Tools.WebControls.MForm.Navigation.XPath;
    using BM.Tools.WebControls.MForm.Navigation.XPath.Predicates;    

    /// <summary>
    /// The factory of the <see cref="PredicateNavigator{T, TPredicate}" />
    /// </summary>
    /// <typeparam name="T">
    /// The type of the navigable object.
    /// </typeparam>    
    internal static class PredicateNavigatorFactory<T>
    {
        /// <summary>
        /// Instantiates a proper <see cref="PredicateNavigator{T,TPredicate}" /> navigator based on the <see cref="Predicate"/> locator object.        
        /// </summary>
        /// <param name="parent">
        /// The parent.
        /// </param>
        /// <param name="locator">
        /// The locator.
        /// </param>
        /// <returns>
        /// the predicate navigator
        /// </returns>
        /// <exception cref="InvalidOperationException">
        /// </exception>
        public static IPredicateNavigator<T> Create(INavigator<T> parent, Predicate locator)
        {
            ConjunctionPredicate conjunction = locator as ConjunctionPredicate;
            if (conjunction != null)
            {
                return new ConjunctionPredicateNavigator<T>(parent, conjunction);
            }

            NamePredicate name = locator as NamePredicate;
            if (name != null)
            {
                return new NamePredicateNavigator<T>(parent, name);
            }

            AlternativesPredicate alternatives = locator as AlternativesPredicate;
            if (alternatives != null)
            {
                return new AlternativesPredicateNavigator<T>(parent, alternatives);
            }

            NegationPredicate negation = locator as NegationPredicate;
            if (negation != null)
            {
                return new NegationPredicateNavigator<T>(parent, negation);
            }

            PositionPredicate position = locator as PositionPredicate;
            if (position != null)
            {
                return new PositionPredicateNavigator<T>(parent, position);
            }

            throw new InvalidOperationException("Unknown predicate type:" + locator.GetType().Name);
        }
    }
}